#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <sys/un.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

typedef struct PacketData {
	int myPort;//port
	int myIP;//ip
	int myID;//id
	int command;
	int cmdArgs;// cmdArgs
	int responseCode;
	int response[4];
} PacketData_t;

#define SERVER_PORT			61255
#define SEND_PORT			SERVER_PORT
#define RECEIVE_PORT		54217



//functia ce trimite mesaje
void trimite_pachet(int port, int ip, int id, int cmd, int cmdArgs)
{
	//partea de trimitere efectiva
	struct sockaddr_in destinatie;
	struct sockaddr_in server;
	int sock, length, n, i;
	char *buf;
	PacketData_t *pd, *pdRecv;
	int porneste = 1;

	pd = (PacketData_t *) malloc( sizeof( * pd) );
	if(!pd)
	{
		perror("pd = NULL\n");
		return;
	}
	pd->myPort = port;
	pd->myIP = ip;
	pd->myID = id;
	pd->command = cmd;
	pd->cmdArgs = cmdArgs;
	pd->responseCode = 0;
	for( i =0; i < 4; i++ )
		pd->response[i] = 0;
	printf("Trimit packet: HEXA: %x, %x, %x, %x, %x\n",
		pd->myPort, pd->myIP, pd->myID, pd->command, pd->cmdArgs);
	printf("VALORIC: %i, %i, %i, %i, %i \n",
		pd->myPort, pd->myIP, pd->myID, pd->command, pd->cmdArgs);
	
	sock= socket(AF_INET, SOCK_DGRAM, 0);
	if (sock < 0) perror("Eroare socket trimitere !");

	if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&porneste,sizeof(porneste)) < 0 )
		perror("set sock opt 2");


	destinatie.sin_family = AF_INET;
	destinatie.sin_addr.s_addr = htonl(INADDR_BROADCAST);
	destinatie.sin_port = htons(SEND_PORT);

		
	//bind
	server.sin_family = AF_INET;
	server.sin_addr.s_addr = htonl(INADDR_ANY);// orice adresa pt server
	server.sin_port = htons(RECEIVE_PORT); // portul sursa


	if (bind (sock, (struct sockaddr *) &server,sizeof(server)) )
	{
		perror("Nu s-a realizat bind\n");
		close(sock);
		return;
	}
	
	//setez permisiunile sa pot trimite BROADCAST
	setsockopt(sock,SOL_SOCKET,SO_BROADCAST,&porneste,sizeof(porneste));
	
	
	length=sizeof(struct sockaddr_in);
	n=sendto(sock, pd, sizeof( *pd), 0, (struct sockaddr *) &destinatie, length);
	if (n < 0)
	{
		perror("Sendto");
		close(sock);
		return;
	}
	


	//primim raspuns de la server o structura PacketData
	buf = (char *) malloc( sizeof(struct PacketData));
	pdRecv = (PacketData_t *) malloc( sizeof( *pdRecv) );
	if (!buf || !pdRecv)
	{
		perror("Eroare alocare buffer de primire.");
		close(sock);
		return;
	}

	n = recvfrom(sock, buf, sizeof( *pdRecv), 0, NULL, NULL);
	if(n<0) 
		write(STDOUT_FILENO,"Nu s-au primit date!\n",21);
	else
	{
		memcpy(pdRecv, buf, n);
		printf("USER Date = %i, size = %i.\n", n, sizeof(*pdRecv));
		printf("USER Am primit: %i %i %i %i %i %i %i %i %i %i\n",
				pdRecv->myPort, pdRecv->myIP, pdRecv->myID, pdRecv->command,
				pdRecv->cmdArgs, pdRecv->responseCode, pdRecv->response[0],
				pdRecv->response[1], pdRecv->response[2], pdRecv->response[3]);
	}

		
	free(buf);
	close(sock);
}



int main()
{
	/*
		write(STDOUT_FILENO,"\nMesaj >",8);
	//determin ID-ul clientului
	get_client_no();
	
	int sock;
	struct sockaddr_in server;
	//creearea socket-ului
	sock=socket(AF_INET, SOCK_DGRAM, 0);
	if (sock < 0) perror("Creare socket ascultare!");
	//bind
	server.sin_family = AF_INET;
	server.sin_addr.s_addr = htonl(INADDR_ANY);// orice adresa pt server
	server.sin_port = htons(CHAT_PORT); // portul pentru server
	if (bind (sock, (struct sockaddr *) &server,sizeof(server)) )
	{
		perror("Nu s-a realizat bind\n");
		exit(1);
	}
		
	char *line;
	char *mesaj;
	
	fd_set read_fds;  
	fd_set temp_fds;  
	int fdmax;        

	FD_ZERO(&read_fds);
	FD_ZERO(&temp_fds);
	
	FD_SET(sock, &read_fds);
	fdmax = CHAT_PORT;

	FD_SET (STDIN_FILENO, &read_fds);

	while (1)
	{
		temp_fds = read_fds;
		
		if (select (fdmax + 1, &temp_fds, NULL, NULL, NULL) == -1) {
			perror ("select");
			return -1;
		}

                if (FD_ISSET (STDIN_FILENO, &temp_fds))
		{
			line=(char *)malloc(100*sizeof(char));
			mesaj=(char *)malloc(100*sizeof(char));
			write(STDOUT_FILENO,"\nMesaj >",8);
			read(STDIN_FILENO,line,100);
			//elimin ENTER din ce am citit de la tastatura
			int i;
			for(i=0;i<strlen(line)-1;i++)
				mesaj[i]=line[i];
			mesaj[strlen(line)]='\0';
			//daca primesc exit, ies din program
			if( strstr(mesaj,"exit") || strstr(mesaj,"EXIT") ) exit(0);
			else trimite_mesaj(mesaj);
		}

		if (FD_ISSET (sock, &temp_fds)) 
		{
			//afisez mesajul primit
			//primire mesaje
			
			int n;
			char buf[80];
			int i;
			for(i=0;i<80;i++)
				buf[i]=' ';
			//nu vrem sa stim de unde primim datele
			n = recvfrom(sock, buf, 80, 0, NULL, NULL); 

			if(n<0) {
				write(STDOUT_FILENO,"Nu s-au primit date!\n",21);
				continue;
			}
			else  
			{
				write(STDOUT_FILENO,"\n Am primit \n",11);
				write(STDOUT_FILENO,buf,strlen(buf));
				write(STDOUT_FILENO,"\nMesaj >",8);
			}
		}
	}

	*/
	int port, ip, id, cmd, args;

	while (1)
	{
		port = ip = id = cmd = args  = 0;
		printf("Introduceti: port id cmd args:");
		scanf("%i %i %i %i", &port, &id, &cmd, &args);
		printf("ati introdus: %i %i %i %i\n", port, id, cmd, args);
		ip = 0x210aa8c0;
		trimite_pachet(port, ip, id, cmd, args);
	}
		
	
	return 0;
}

